package com.tt.fashionWebSite.service.imp;

import com.tt.fashionWebSite.dao.ChiTietHoaDonDao;
import com.tt.fashionWebSite.dao.ChiTietSanPhamDao;
import com.tt.fashionWebSite.dao.HoaDonDao;
import com.tt.fashionWebSite.dao.ThongTinThanhVienDao;
import com.tt.fashionWebSite.domain.*;
import com.tt.fashionWebSite.dto.CartDto;
import com.tt.fashionWebSite.dto.ChiTietSanPhamFullDto;
import com.tt.fashionWebSite.dto.GioHangDto;
import com.tt.fashionWebSite.dto.PaymentDto;
import com.tt.fashionWebSite.service.GenericService;
import com.tt.fashionWebSite.service.PaymentService;
import com.tt.fashionWebSite.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by isoft-work 5 on 12/21/2014.
 */
@Service("paymentService")
public class PaymentServiceImp extends GenericService implements PaymentService {
   @Autowired
   @Qualifier("thongTinThanhVien")
   private ThongTinThanhVienDao thongTinThanhVienDao;

   @Autowired
   @Qualifier("hoaDon")
   private HoaDonDao hoaDonDao;

   @Autowired
   @Qualifier("chiTietHoaDon")
   private ChiTietHoaDonDao chiTietHoaDonDao;

   @Autowired
   @Qualifier("chiTietSanPham")
   private ChiTietSanPhamDao chiTietSanPhamDao;

   @Override
   @Transactional(propagation = Propagation.REQUIRED)
   public PaymentDto billPayment(PaymentDto paymentDto, GioHangDto gioHangDto) {
      try {
         saveBillForOrderPayPal(paymentDto, gioHangDto);

         return paymentDto;
      }
      catch (Exception ex) {
         return null;
      }
   }

   @Override
   public void payPalCheckOut(HttpServletRequest request, HttpServletResponse response, GioHangDto gioHangDto) throws ServletException, IOException {
      Double paymentAmount = gioHangDto.getTotalMoney();
      String count = gioHangDto.getTotal().toString();
      String contextPath = request.getContextPath();
      ExchangeRate exchangeRate = new ExchangeRate();
      String returnURL = ISSConstants.HOST + contextPath +"/service/payment/payPal/success";

      String cancelURL = ISSConstants.HOST + contextPath +"/service/payment/payPal/cancel";

      Map item = new HashMap();
      item.put("name", contextPath);
      // change current VND->$
      String finalAmount = String.valueOf(Math.round(paymentAmount/exchangeRate.getVndUsdRate()*100.0)/100.0);
      item.put("amt", finalAmount);
      item.put("qty", count);

      PaypalFunctions ppf = new PaypalFunctions();
      HashMap nvp = ppf.setExpressCheckout(finalAmount, returnURL,
            cancelURL, item);
      String strAck = nvp.get("ACK").toString();
      if (strAck != null && strAck.equalsIgnoreCase("Success")) {
         // ' Redirect to paypal.com
         String redirectURL = "https://www.sandbox.paypal.com/incontext?token="
               + nvp.get("TOKEN").toString();

         response.sendRedirect(redirectURL);
//         ppf.RedirectURL(response, nvp.get("TOKEN").toString());

      } else {
         // Display a user friendly Error on the page using any of the
         // following error information returned by PayPal

         String ErrorCode = nvp.get("L_ERRORCODE0").toString();
         String ErrorShortMsg = nvp.get("L_SHORTMESSAGE0").toString();
         String ErrorLongMsg = nvp.get("L_LONGMESSAGE0").toString();
         String ErrorSeverityCode = nvp.get("L_SEVERITYCODE0").toString();
      }
   }

   @Override
   @Transactional(propagation = Propagation.REQUIRED)
   public void payPalSuccess(HttpServletRequest request, HttpServletResponse response, GioHangDto gioHangDto, PaymentDto paymentDto) throws ServletException, IOException {
      String token = request.getParameter("token");
      String payerId = request.getParameter("PayerID");

      if (token != null) {
         PaypalFunctions ppf = new PaypalFunctions();
         HashMap nvp = ppf.getPaymentDetails(token);

         String strAck = nvp.get("ACK").toString();
         String finalPaymentAmount = null;
         if (strAck != null
               && (strAck.equalsIgnoreCase("Success") || strAck
               .equalsIgnoreCase("SuccessWithWarning"))) {
            finalPaymentAmount = nvp.get("AMT").toString();
         }
         String serverName = request.getServerName();

         Map item = new HashMap();
         item.put("name", nvp.get("L_PAYMENTREQUEST_0_NAME0"));
         item.put("amt", nvp.get("L_PAYMENTREQUEST_0_AMT0"));
         item.put("qty", nvp.get("L_PAYMENTREQUEST_0_QTY0"));

         nvp = ppf.confirmPayment(token, payerId, finalPaymentAmount,
               serverName, item);

         strAck = nvp.get("ACK").toString();


         if (strAck != null
               && (strAck.equalsIgnoreCase("Success") || strAck
               .equalsIgnoreCase("SuccessWithWarning"))) {
// TODO: Proceed with desired action after the payment
            saveBillForOrderPayPal(paymentDto, gioHangDto);
         } else {
            // Display a user friendly Error on the page using any of the
            // following error information returned by PayPal

            String ErrorCode = nvp.get("L_ERRORCODE0").toString();
            String ErrorShortMsg = nvp.get("L_SHORTMESSAGE0").toString();
            String ErrorLongMsg = nvp.get("L_LONGMESSAGE0").toString();
            String ErrorSeverityCode = nvp.get("L_SEVERITYCODE0")
                  .toString();

            response.getWriter()
                  .println(
                        "<script>\n alert(\"Payment Failed\");\n// add relevant message above or remove the line if not required \n window.onload = function(){\nif(window.opener){\nwindow.close();\n}\nelse{\nif(top.dg.isOpen() == true){\ntop.dg.closeFlow();\nreturn true;\n}\n}\n};\n</script>");
         }
      }
   }

   @Override
   public void baoKimPayment(HttpServletRequest request, HttpServletResponse response, GioHangDto gioHangDto) throws ServletException, IOException {
      String contextPath = request.getContextPath();
      BaoKimPayment kimPayment = new BaoKimPayment();
      Date now = new Date();
      String idHD = "HD" + now.getTime();
      String totalMoney = gioHangDto.getTotalMoney().toString();
      String urlSuccess = ISSConstants.HOST + contextPath +"/service/payment/baoKim/success";
      String urlCancel = ISSConstants.HOST + contextPath +"/service/payment/baoKim/cancel";

      String urlRequest = kimPayment.createRequestUrl(idHD, ISSConstants.EMAIL_PAYMENT, totalMoney, "0", "0", "", urlSuccess, urlCancel, "");
      response.sendRedirect(urlRequest);
   }

   @Override
   @Transactional(propagation = Propagation.REQUIRED)
   public void kimBaoSuccess(String idHD, GioHangDto gioHangDto, PaymentDto paymentDto) throws ServletException, IOException {
      saveBillForBaoKim(idHD, paymentDto, gioHangDto);
   }

   @Override
   public void nganLuongPayment(HttpServletRequest request, HttpServletResponse response, GioHangDto gioHangDto) throws ServletException, IOException {
      String contextPath = request.getContextPath();
      NganLuongPayment nganLuongPayment = new NganLuongPayment();
      Date now = new Date();
      String idHD = "HD" + now.getTime();
      String totalMoney = gioHangDto.getTotalMoney().toString();
      String urlSuccess = ISSConstants.HOST + contextPath +"/service/payment/nganLuong/success";
      String urlCancel = ISSConstants.HOST + contextPath +"/service/payment/nganLuong/cancel";

      String urlRequest = nganLuongPayment.buildCheckoutUrl(urlSuccess, "uitquocthang@gmail.com", idHD, totalMoney, "Thanh toan");
      response.sendRedirect(urlRequest);
   }

   private void saveBillForOrderPayPal(PaymentDto paymentDto, GioHangDto gioHangDto) {
      // update user ifo
      ThongTinThanhVien thongTinThanhVien = thongTinThanhVienDao.findById(paymentDto.getThongTinThanhVien().getMaTV());
      thongTinThanhVien.setDiaChi(paymentDto.getThongTinThanhVien().getDiaChi());
      thongTinThanhVien.setHo(paymentDto.getThongTinThanhVien().getHo());
      thongTinThanhVien.setTen(paymentDto.getThongTinThanhVien().getTen());
      thongTinThanhVien.setGioiTinh(paymentDto.getThongTinThanhVien().getGioiTinh());
      thongTinThanhVien.setNgaySinh(paymentDto.getThongTinThanhVien().getNgaySinh());
      thongTinThanhVien.setSoDT(paymentDto.getThongTinThanhVien().getSoDT());
      thongTinThanhVienDao.update(thongTinThanhVien);

      // insert bill
      Date now = new Date();
      String idHD = "HD" + now.getTime();
      HoaDon hoaDon = new HoaDon();
      hoaDon.setMaHD(idHD);
      hoaDon.setNgayLapHD(now);
      hoaDon.setNgayLapHD(now);
      hoaDon.setNgayGiao(null);
      hoaDon.setNgayNhan(null);
      hoaDon.setGhiChu(paymentDto.getNote());
      if(paymentDto.getType() == 0) {
         hoaDon.setThanhToan(Long.parseLong("0"));
      }
      else {
         hoaDon.setThanhToan(Long.parseLong("1"));
      }
      hoaDon.setTrangThai(Long.parseLong("0"));
      hoaDon.setTongTien(gioHangDto.getTotalMoney());
      hoaDon.setThongTinThanhVien(thongTinThanhVien);

      if(paymentDto.getNguoiNhan() == null) {
         hoaDon.setDiaChiNN(paymentDto.getThongTinThanhVien().getDiaChi());
         hoaDon.setHoTenNN(paymentDto.getThongTinThanhVien().getHo() + " " + paymentDto.getThongTinThanhVien().getTen());
         hoaDon.setSoDTNN(paymentDto.getThongTinThanhVien().getSoDT());
      }
      else {
         hoaDon.setDiaChiNN(paymentDto.getNguoiNhan().getDiaChi());
         hoaDon.setHoTenNN(paymentDto.getNguoiNhan().getHo() + " " + paymentDto.getNguoiNhan().getTen());
         hoaDon.setSoDTNN(paymentDto.getNguoiNhan().getSoDT());
      }
      hoaDonDao.insert(hoaDon);

      // insert detail bill
      List<CartDto> carts = gioHangDto.getCarts();
      for(int i = 0; i < carts.size(); i++) {
         ChiTietHoaDon chiTietHoaDon = new ChiTietHoaDon();
         chiTietHoaDon.setHoaDon(hoaDon);
         chiTietHoaDon.setSoLuong(Long.parseLong(carts.get(i).getCount().toString()));
         chiTietHoaDon.setTongGia(Double.parseDouble(carts.get(i).getGiaBan().toString()));
         ChiTietSanPham chiTietSanPham = chiTietSanPhamDao.findById(carts.get(i).getChiTietSanPham().getMaCTSP());
         chiTietSanPham.setMaCTSP(carts.get(i).getChiTietSanPham().getMaCTSP());
         chiTietHoaDon.setChiTietSanPham(chiTietSanPham);
         chiTietHoaDonDao.insert(chiTietHoaDon);
         // update number product
         chiTietSanPham.setSoLuong(chiTietSanPham.getSoLuong() - carts.get(i).getCount());
         chiTietSanPhamDao.update(chiTietSanPham);
      }
   }

   private void saveBillForBaoKim(String idHD, PaymentDto paymentDto, GioHangDto gioHangDto) {
      // update user ifo
      ThongTinThanhVien thongTinThanhVien = thongTinThanhVienDao.findById(paymentDto.getThongTinThanhVien().getMaTV());
      thongTinThanhVien.setDiaChi(paymentDto.getThongTinThanhVien().getDiaChi());
      thongTinThanhVien.setHo(paymentDto.getThongTinThanhVien().getHo());
      thongTinThanhVien.setTen(paymentDto.getThongTinThanhVien().getTen());
      thongTinThanhVien.setGioiTinh(paymentDto.getThongTinThanhVien().getGioiTinh());
      thongTinThanhVien.setNgaySinh(paymentDto.getThongTinThanhVien().getNgaySinh());
      thongTinThanhVien.setSoDT(paymentDto.getThongTinThanhVien().getSoDT());
      thongTinThanhVienDao.update(thongTinThanhVien);

      // insert bill
      Date now = new Date();
      HoaDon hoaDon = new HoaDon();
      hoaDon.setMaHD(idHD);
      hoaDon.setNgayLapHD(now);
      hoaDon.setNgayLapHD(now);
      hoaDon.setNgayGiao(null);
      hoaDon.setNgayNhan(null);
      hoaDon.setGhiChu(paymentDto.getNote());
      if(paymentDto.getType() == 0) {
         hoaDon.setThanhToan(Long.parseLong("0"));
      }
      else {
         hoaDon.setThanhToan(Long.parseLong("1"));
      }
      hoaDon.setTrangThai(Long.parseLong("0"));
      hoaDon.setTongTien(gioHangDto.getTotalMoney());
      hoaDon.setThongTinThanhVien(thongTinThanhVien);

      if(paymentDto.getNguoiNhan() == null) {
         hoaDon.setDiaChiNN(paymentDto.getThongTinThanhVien().getDiaChi());
         hoaDon.setHoTenNN(paymentDto.getThongTinThanhVien().getHo() + " " + paymentDto.getThongTinThanhVien().getTen());
         hoaDon.setSoDTNN(paymentDto.getThongTinThanhVien().getSoDT());
      }
      else {
         hoaDon.setDiaChiNN(paymentDto.getNguoiNhan().getDiaChi());
         hoaDon.setHoTenNN(paymentDto.getNguoiNhan().getHo() + " " + paymentDto.getNguoiNhan().getTen());
         hoaDon.setSoDTNN(paymentDto.getNguoiNhan().getSoDT());
      }
      hoaDonDao.insert(hoaDon);

      // insert detail bill
      List<CartDto> carts = gioHangDto.getCarts();
      for(int i = 0; i < carts.size(); i++) {
         ChiTietHoaDon chiTietHoaDon = new ChiTietHoaDon();
         chiTietHoaDon.setHoaDon(hoaDon);
         chiTietHoaDon.setSoLuong(Long.parseLong(carts.get(i).getCount().toString()));
         chiTietHoaDon.setTongGia(Double.parseDouble(carts.get(i).getGiaBan().toString()));
         ChiTietSanPham chiTietSanPham = chiTietSanPhamDao.findById(carts.get(i).getChiTietSanPham().getMaCTSP());
         chiTietSanPham.setMaCTSP(carts.get(i).getChiTietSanPham().getMaCTSP());
         chiTietHoaDon.setChiTietSanPham(chiTietSanPham);
         chiTietHoaDonDao.insert(chiTietHoaDon);
         // update number product
         chiTietSanPham.setSoLuong(chiTietSanPham.getSoLuong() - carts.get(i).getCount());
         chiTietSanPhamDao.update(chiTietSanPham);
      }
   }
}
